Zadanie: wysyłanie rezerwacji do API
Na tym etapie formularz jest już prawie gotowy, ale nie do końca. Możemy wybierać liczbę gości, liczbę godzin, termin rezerwacji, godzinę rezerwacji, a do tego na bieżąco widzimy, które stoliki są wolne. To jednak wciąż za mało, aby uznać naszą podstronę rezerwacji za gotową.
Po pierwsze, widzimy jakie stoliki są wolne, a jakie zajęte, ale nie możemy wskazać, który chcielibyśmy wybrać jako klient.
Po drugie, kiedy wybierzemy już wszystkie opcje, chcielibyśmy wysłać naszą rezerwację do serwera, ale nasz button "Book a table" po kliknięciu jeszcze niczego takiego nie robi...
Wykonanie obu tych funkcjonalności będzie teraz Twoim zadaniem.
Wybór stolika
Warto zacząć od możliwości zaznaczenia dostępnego stolika za pomocą kliknięcia.
Jak to w ogóle powinno działać? Klient w każdej chwili powinien być w stanie kliknąć na dowolny wolny stolik. Kliknięcie na taki stolik powinno zmieniać jego wygląd, np. nadawać nową klasę, która doda mu dodatkowy border albo inny kolor. Powinno również zapisywać informacje o wybranym stoliku w instancji Bookingu, np. jako właściwość. Po co? Po to, aby później, przy próbie wysyłki rezerwacji do serwera, mieć dostęp do informacji, jaki stolik został wybrany przez klienta.
To dokładnie ten sam pomysł, jak w przypadku AmountWidget-ów. Zawsze, gdy tworzyliśmy w jakiejś klasie ich instancje, od razu przypisywaliśmy referencje do nich jako właściwości. Po co? W tym samym celu. Żeby w przyszłości mieć łatwy dostęp do ich wartości w pozostałych metodach.
Podsumowując, na pewno kliknięcie na wolny stolik powinno zmienić jego wygląd oraz zapisać jego numerek do właściwości w instancji Booking.
Dodatkowo musimy założyć, że:
- klient nie może wybrać stolika, który jest już zajęty,
- wybór stolika powinien być resetowany przy zmianie godziny, daty, liczby gości oraz liczby godzin,
- kliknięcie na zaznaczony stolik po raz kolejny, również powinno wyzerować wybór i przywrócić podstawowy wygląd stolika,
- jeśli klient zaznaczył już stolik, a po tym klika jednak na inny, to w takiej sytuacji trzeba zaktualizować informację o wybranym stoliku oraz zabrać klasę "wyboru" ze starego stolika.
- nie chcemy nasłuchiwać na stoliki pojedynczo, zastosuj event delegation.
Całość powinna na końcu działać następująco:
Uwaga! Staraj się trzymać praktyk, które wykorzystywaliśmy przez cały projekt, czyli np. do przechowywania selektorów i klas wykorzystuj obiekty select i classNames, czy też przypisuj ew. referencje do elementów HTML w obiekcie thisBooking.dom.
Wskazówki
- Tak naprawdę wykonywaliśmy już kiedyś podobne ćwiczenie. Pamiętasz naszą aplikację z książkami? Stworzyliśmy tam mechanizm wyboru ulubionych książek, który działa naprawdę bardzo podobnie! Z tym że tam było nawet trudniej, bo pozwalaliśmy na wybieranie więcej niż jednej książki. Tutaj zawsze będziemy mieć informację tylko o jednym stoliku.
- Specjalną klasę, którą można by nadać wybranemu stolikowi, musisz dopiero utworzyć. Nie ma jej jeszcze w arkuszu stylów.
- Jak sprawdzić, czy stolik jest wolny? Pamiętaj, że każdy zajęty stolik otrzymuje od
updateDOMklasębooked. Aby sprawdzić, czy stolik jest wolny, nie trzeba więc sprawdzać bezpośrednio obiektuthisBooking.booked. Wystarczy, że sprawdzimy, czy stolik ma klasębooked. Jeśli ma, to na pewno jest zajęty! Jeśli nie, to na pewno jest wolny! - Jak zadbać o "zerowanie" wyboru stolika przy zmianie godziny czy daty? Czy trzeba dodawać jakieś nasłuchiwacze na inputy, które po wykryciu zmiany, wyzerują właściwość i odbiorą wybranemu stolikowi klasę "wyboru"? Nie... Można to zrobić znacznie prościej. Odpowiemy jednak enigmatycznie – sprawdź, kiedy uruchamiana jest funkcja
updateDOM;)
Spróbuj wykonać to zadanie bez naszej pomocy. Wspomagaj się również kodem, który napisaliśmy w aplikacji książek. Naprawdę dużo Ci on podpowie. Jeśli przez dłuższy czas nie uda Ci się niczego wymyślić, to poniżej przedstawiamy dokładniejsze kroki, od których możesz zacząć.
Pokaż wskazówkę Ukryj wskazówkę
-
Zacznij od utworzenia w CSS nowej klasy. Nazwij ją np.
selectedi zadbaj, aby była podobna do klasybooked, ale np. dodawała jeszcze jakiś border albo inny background. Chodzi po prostu o to, aby klient łatwo mógł odróżnić stoliki faktycznie zarezerwowane od tego, który sam zaznaczył. -
Następnie przygotuj w konstruktorze właściwość, która w założeniu będzie przechowywać informacje o wybranym stoliku.
-
Przygotuj w metodzie
renderdostęp do diva ze stolika. Co ważne, całego diva. -
Dodaj do
initWidgetsnowy nasłuchiwacz, który przy wykryciu kliknięcia w diva ze stolikami włączy nową metodę. Np.initTables. -
Metoda ta powinna sprawdzać, czy kliknięto faktycznie na stolik. Jeśli tak, to powinna sprawdzać, czy stolik jest wolny. Jeśli nie, to może pokazywać np. alert z komunikatem o zajętości stolika. Jeśli jednak jest wolny, to należy przypisać numer tego stolika do właściwości, którą wcześniej przygotowaliśmy w konstruktorze, tak aby cała aplikacja miała dostęp do tej informacji. Należy również dodać do tego stolika klasę
selected. -
Pamiętaj przy tym, że zanim dodasz do wybranego stolika klasę
selected, to należy sprawdzić, czy czasem inny stolik już takiej nie ma. I jeśli ma, to mu ją zabrać. Samej właściwości nie musimy jednak wcześniej zerować, bo przecież i tak za moment nadpiszemy ją numerkiem nowego stolika. Musimy więc zadbać tylko o zabranie klasy staremu stolikowi, samą właściwością się nie martw.
To już naprawdę dużo. Od tej chwili kliknięcie na stolik zajęty, powinno pokazywać od razu alert z informacją o zajętości. Kliknięcie na wolny stolik powinno powodować zmianę jego wyglądu i, co ważniejsze, przypisywać do jakiejś właściwości w Booking informacje o numerze tego wybranego stolika. Co więcej, jeśli w momencie wyboru nowego stoliku, inny był już wybrany wcześniej, to ten wcześniejszy powinien wrócić wyglądem do normalności, czyli stracić klasę selected.
To, co Ci pozostało, to już tylko poniższe funkcjonalności:
- wybór stolika powinien być resetowany przy zmianie godziny, daty, liczby gości oraz liczby godzin,
- kliknięcie na zaznaczony już stolik po raz kolejny, powinno również resetować wybór zapisany w JS oraz zabierać klasę "wyboru".
Wysyłka danych na serwer
Druga część zadania będzie wyraźnie łatwiejsza. Musimy bowiem przygotować funkcję, która po prostu wyślę pod odpowiedni adres na serwerze informacje o rezerwacji. Tyle. Tak naprawdę ta metoda będzie więc prawie identyczna jak sendOrder, które napisaliśmy w klasie Cart. Inny będzie jedynie link, no i zawartość obiektu payload.
Twoim zadaniem będzie więc:
- Zadbanie o to, aby próba wysyłki formularza, kończyła się włączeniem funkcji
sendBooking. - Przygotowanie funkcji
sendBooking, która wyśle pod adreslocalhost:3131/bookingobiekt o następującej strukturze:
{
"date": data wybrana w datePickerze
"hour": godzina wybrana w hourPickerze (w formacie HH:ss)
"table": numer wybranego stolika (lub null jeśli nic nie wybrano)
"duration": liczba godzin wybrana przez klienta
"ppl": liczba osób wybrana przez klienta
"starters": [],
"phone": numer telefonu z formularza,
"address": adres z formularza
}
Przy czym ppl, duration i table powinny być liczbami. Nie mogą być tekstem.
Nie opisaliśmy tutaj tylko jednej właściwości – starters. W Cart.sendOrder mieliśmy jedną specjalną właściwość, która była tablicą, uzupełnianą dopiero pod obiektem payload. Tutaj jest podobnie. starters powinno być tablicą, która zawiera wartości zaznaczonych checkboxów w sekcji "Starters".
Jeśli zaznaczono tylko "water", to starters powinno być tablicą ['water']. Jeśli zaznaczono Bread, to starters powinno być tablicą ['water', 'bread']. Jeśli nie zaznaczono nic, to powinno być pustą tablicą.
Poradzisz z tym sobie, prawda? Przypomnij sobie ponownie projekt aplikacji z książkami. Robiliśmy tam coś podobnego w funkcjonalności z filtrami.
Użycie makeBooked...
O mało nie zapomnieliśmy! Pamiętaj, że request, który wykonamy, nie odświeża naszej strony. Z jednej strony, to oczywiście plus, ale z drugiej, w naszym przypadku, ma pewną wadę. Oznacza to bowiem, że w thisBooking.booked nie będzie zapisana informacja o naszej rezerwacji. Tak naprawdę, dopiero odświeżenie strony i pobranie danych z serwera, spowodowałoby ponowne przygotowanie thisBooking.booked, w którym nowa rezerwacja już by się znalazła.
Co możemy z tym fantem zrobić? Tak naprawdę pobieranie danych to tylko jeden etap przygotowania thisBooking.booked. Zauważ, że gdy są one już pobrane, to rezerwacje są dodawane jedna po jednej, za pomocą funkcji makeBooked. Wystarczy więc, że za pomocą tej samej funkcji, w przypadku sukcesu naszego requestu do serwera, będziemy dodawać do thisBooking.booked również naszą nową rezerwację!
Powodzenia!